home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1999-06-13 | 20.1 KB | 735 lines | [ TEXT/CWIE]
// Copyright (C) 1999 Eric Roccasecca. All rights reserved. #include "X_Ray_Priv.h" #include "Layers.h" // Disposes of all memory allocated for a transparent or clear window OSErr X_Ray_DisposeWindow (X_Ray_WindowHandle deadWin) { HLock ((Handle)deadWin); X_Ray_FixOwningListEnds (deadWin); // fix list head if necessary if ((*deadWin)->nextWindow) (*((*deadWin)->nextWindow))->previousWindow = (*deadWin)->previousWindow; if ((*deadWin)->previousWindow) (*((*deadWin)->previousWindow))->nextWindow = (*deadWin)->nextWindow; // release allocated memory DisposeGWorld ((*deadWin)->underBuffer); DisposeGWorld ((*deadWin)->contentBuffer); DisposeGWorld ((*deadWin)->mixBuffer); DisposeGWorld ((*deadWin)->maskBuffer); DisposeRgn ((*deadWin)->transparentUpdateRgn); HUnlock ((Handle)deadWin); DisposeHandle ((Handle)deadWin); } // fixes the list ends if the window is the at an end of the list void X_Ray_FixOwningListEnds (X_Ray_WindowHandle theWindow) { if (((*theWindow)->windowKind)&kTSMWindow) { if (theWindow == gCommRec.tsmWindowList) gCommRec.tsmWindowList = (*theWindow)->nextWindow; if (theWindow == gCommRec.tsmLastWindow) gCommRec.tsmLastWindow = (*theWindow)->previousWindow; } else { if (theWindow == (*((*theWindow)->owner))->windowList) (*((*theWindow)->owner))->windowList = (*theWindow)->nextWindow; if (theWindow == (*((*theWindow)->owner))->lastWindow) (*((*theWindow)->owner))->lastWindow = (*theWindow)->previousWindow; } } // retrieves the transparent window record associated with a specific window // will not return a window record for a trans window that has been marked as disposed X_Ray_WindowHandle X_Ray_GetWindowRec (WindowPtr theWindow) { X_Ray_AppRecHandle curApp; X_Ray_WindowHandle curTransWindow = nil; if (theWindow == nil) return nil; // first, check tsm window list curTransWindow = gCommRec.tsmWindowList; while (curTransWindow) { if ((*curTransWindow)->theWindow == theWindow) { // found the window, but is it marked and disposed return curTransWindow; } curTransWindow = (*curTransWindow)->nextWindow; } // second, check application window list curApp = gCommRec.appList; while (curApp) { curTransWindow = (*curApp)->windowList; while (curTransWindow) // scan the transparent window list { if ((*curTransWindow)->theWindow == theWindow) { // found the window, but is it marked and disposed return curTransWindow; } curTransWindow = (*curTransWindow)->nextWindow; } curApp = (*curApp)->nextApp; } return nil; } // returns a particular feature for a transparent or clear window long X_Ray_GetWindowFeature (WindowPtr theWindow, short kFeatureKind) { X_Ray_WindowHandle curWin; long result = 0; curWin = X_Ray_GetWindowRec (theWindow); if (curWin) { switch (kFeatureKind) { case kTransWindowUnderBuffer: result = (long)(*curWin)->underBuffer; break; case kTransWindowContentBuffer: result = (long)(*curWin)->contentBuffer; break; case kTransWindowMixBuffer: result = (long)(*curWin)->mixBuffer; break; case kTransWindowTransparency: result = (long)(*curWin)->transparency; break; case kTransWindowOwner: result = (long)&(*curWin)->owner; break; case kX_RayWindowKind: result = (*curWin)->windowKind; break; case kClearWindowClearColor: result = (long)&(*curWin)->clearColor; break; case kTransWindowStandardWDEF: result = (long)(*curWin)->origWDEF; break; default: break; } } return result; } // globals used by the function PortIsOnScreen GrafPtr gLastPortCheckedAsWindow = nil; Boolean gLastPortCheckedWasWindow = false; // see if a port is a window // compare its base address to any screen device // is there a better way to do this? Boolean PortIsOnScreen (GrafPtr thePort) { GDHandle curDevice; if (gLastPortCheckedAsWindow == thePort) return gLastPortCheckedWasWindow; gLastPortCheckedAsWindow = thePort; gLastPortCheckedWasWindow = false; curDevice = GetDeviceList(); while (curDevice) { if ((*curDevice)->gdFlags&(1<<screenDevice)) // only check devices that are screens { if (((CGrafPtr)thePort)->portVersion&0xC000) // is color port { if (GetPixBaseAddr((*curDevice)->gdPMap) == GetPixBaseAddr(((CGrafPtr)thePort)->portPixMap)) { gLastPortCheckedWasWindow = true; return gLastPortCheckedWasWindow; } } else // is BW port { if (GetPixBaseAddr((*curDevice)->gdPMap) == thePort->portBits.baseAddr) { gLastPortCheckedWasWindow = true; return gLastPortCheckedWasWindow; } } } curDevice = (GDHandle)(*curDevice)->gdNextGD; } return gLastPortCheckedWasWindow; } // see if a BitMap/PixMap is on screen // compare its base address to any screen device Boolean BitMapIsOnScreen (const BitMap *theBMap) { GDHandle curDevice; Boolean isScreen = false; curDevice = GetDeviceList(); while (curDevice) { if ((*curDevice)->gdFlags&(1<<screenDevice)) // only check devices that are screens { if ((theBMap->rowBytes)&0xC000) // is color port { if (GetPixBaseAddr((*curDevice)->gdPMap) == theBMap->baseAddr) // even though theBMap is color, because this is a comparison to a screen this appears to be legal { isScreen = true; return isScreen; } } else // is BW port { if (GetPixBaseAddr((*curDevice)->gdPMap) == theBMap->baseAddr) { isScreen = true; return isScreen; } } } curDevice = (GDHandle)(*curDevice)->gdNextGD; } return isScreen; } // globals used by the function PortDoesIntersect X_Ray_WindowHandle gLastPortIntersection = nil; RgnHandle gIntersectCurPortVisRgn, gIntersectCurTransVisRgn; // intialized in qdPatches.c // determines if a port is on screen (by calling PortIsOnScreen) and if it // intersects at least one transparent window and intersects the current drawRgn // returns back-most transparent window intersected X_Ray_WindowHandle PortDoesIntersect (GrafPtr thePort, RgnHandle drawRgn) { X_Ray_WindowHandle curTransWindow; X_Ray_AppRecHandle curApp; GrafPtr curPort; if (thePort == nil) // just to be safe return nil; // not on screen so there are no intersections possible if (!PortIsOnScreen (thePort)) return nil; GetPort (&curPort); gLastPortIntersection = nil; CopyRgn (thePort->visRgn, gIntersectCurPortVisRgn); X_Ray_LocalToGlobalRgn (gIntersectCurPortVisRgn); // examine transparent TSM window list curTransWindow = gCommRec.tsmWindowList; while (curTransWindow) { SetPort ((*curTransWindow)->theWindow); CopyRgn (((*curTransWindow)->theWindow)->visRgn, gIntersectCurTransVisRgn); X_Ray_LocalToGlobalRgn (gIntersectCurTransVisRgn); SectRgn (gIntersectCurPortVisRgn, gIntersectCurTransVisRgn, gIntersectCurTransVisRgn); SectRgn (drawRgn, gIntersectCurTransVisRgn, gIntersectCurTransVisRgn); if (!EmptyRgn (gIntersectCurTransVisRgn)) gLastPortIntersection = curTransWindow; curTransWindow = (*curTransWindow)->nextWindow; } // examine application transparent window lists curApp = gCommRec.appList; while (curApp) { curTransWindow = (*curApp)->windowList; while (curTransWindow) { SetPort ((*curTransWindow)->theWindow); CopyRgn (((*curTransWindow)->theWindow)->visRgn, gIntersectCurTransVisRgn); X_Ray_LocalToGlobalRgn (gIntersectCurTransVisRgn); SectRgn (gIntersectCurPortVisRgn, gIntersectCurTransVisRgn, gIntersectCurTransVisRgn); SectRgn (drawRgn, gIntersectCurTransVisRgn, gIntersectCurTransVisRgn); if (!EmptyRgn (gIntersectCurTransVisRgn)) gLastPortIntersection = curTransWindow; curTransWindow = (*curTransWindow)->nextWindow; } curApp = (*curApp)->nextApp; } SetPort (curPort); return gLastPortIntersection; } // reorders an app's transparent window list void ReorderWindow (X_Ray_WindowHandle theWindow, short reorderMethod, WindowPtr switchWindow) { WindowPtr curWindow; X_Ray_WindowHandle curTransWindow, lastTransWindow; X_Ray_AppRecHandle curApp; if ((*theWindow)->windowKind&kTSMWindow) { curTransWindow = gCommRec.tsmWindowList; GetFrontServiceWindow (&curWindow); // get front TSM window } else { curApp = (*theWindow)->owner; curTransWindow = (*((*theWindow)->owner))->windowList; curWindow = GetFirstLayerWindow ((LayerPtr)(*curApp)->appGlobalWindow); // get front of window list of owner app } switch (reorderMethod) { // these methods bring the window to front case kROMethod_MoveWindow: case kROMethod_BringToFront: case kROMethod_SelectWindow: case kROMethod_DragWindow: if (theWindow == curTransWindow) // window is already front most break; if ((*theWindow)->nextWindow) (*(*theWindow)->nextWindow)->previousWindow = (*theWindow)->previousWindow; if ((*theWindow)->previousWindow) (*(*theWindow)->previousWindow)->nextWindow = (*theWindow)->nextWindow; if ((*theWindow)->windowKind&kTSMWindow) // TSM { if ((gCommRec.tsmLastWindow == theWindow) && (*theWindow)->previousWindow) // fix end of list gCommRec.tsmLastWindow = (*theWindow)->previousWindow; (*theWindow)->nextWindow = gCommRec.tsmWindowList; gCommRec.tsmWindowList = theWindow; } else // app window { if (((*((*theWindow)->owner))->lastWindow == theWindow) && (*theWindow)->previousWindow) // fix end of list (*((*theWindow)->owner))->lastWindow = (*theWindow)->previousWindow; (*theWindow)->nextWindow = (*((*theWindow)->owner))->windowList; (*((*theWindow)->owner))->windowList = theWindow; } (*theWindow)->previousWindow = nil; (*(*theWindow)->nextWindow)->previousWindow = theWindow; break; // these methods move a window in the window list case kROMethod_HideWindow: case kROMethod_ShowHide: case kROMethod_SendBehind: if (switchWindow == (*theWindow)->theWindow) // no need to move a window behind itself break; // moving to end of window list if ((switchWindow == nil) || (switchWindow && ((WindowPeek)switchWindow)->nextWindow == nil)) { if ((*theWindow)->nextWindow) { if ((*theWindow)->windowKind&kTSMWindow) { // fix list head if (gCommRec.tsmWindowList == theWindow) gCommRec.tsmWindowList = (*theWindow)->nextWindow; } else { // fix list head if ((*((*theWindow)->owner))->windowList == theWindow) (*((*theWindow)->owner))->windowList = (*theWindow)->nextWindow; } (*(*theWindow)->nextWindow)->previousWindow = (*theWindow)->previousWindow; // only update the previous window if there really is a next window if ((*theWindow)->previousWindow) (*(*theWindow)->previousWindow)->nextWindow = (*theWindow)->nextWindow; } if ((*theWindow)->windowKind&kTSMWindow) { // fix list end if (gCommRec.tsmLastWindow != theWindow) { (*gCommRec.tsmLastWindow)->nextWindow = theWindow; (*theWindow)->previousWindow = gCommRec.tsmLastWindow; gCommRec.tsmLastWindow = theWindow; } } else { // fix list end if ((*((*theWindow)->owner))->lastWindow != theWindow) { (*(*((*theWindow)->owner))->lastWindow)->nextWindow = theWindow; (*theWindow)->previousWindow = (*((*theWindow)->owner))->lastWindow; (*((*theWindow)->owner))->lastWindow = theWindow; } } (*theWindow)->nextWindow = nil; } else // moving within the list { while (curWindow) { if (curTransWindow) // keep track of last transwin found lastTransWindow = curTransWindow; curTransWindow = X_Ray_GetWindowRec (curWindow); if (curWindow == switchWindow) { if (curTransWindow == nil) curTransWindow = lastTransWindow; if ((curTransWindow != theWindow) && ((*curTransWindow)->nextWindow != theWindow)) // no need to move if already there { if ((*theWindow)->nextWindow) { // fix list head if ((*theWindow)->windowKind&kTSMWindow) { if (gCommRec.tsmWindowList == theWindow) gCommRec.tsmWindowList = (*theWindow)->nextWindow; } else { if ((*((*theWindow)->owner))->windowList == theWindow) (*((*theWindow)->owner))->windowList = (*theWindow)->nextWindow; } (*(*theWindow)->nextWindow)->previousWindow = (*theWindow)->previousWindow; } if ((*theWindow)->previousWindow) (*(*theWindow)->previousWindow)->nextWindow = (*theWindow)->nextWindow; (*theWindow)->nextWindow = (*curTransWindow)->nextWindow; (*theWindow)->previousWindow = curTransWindow; if ((*curTransWindow)->nextWindow) (*(*curTransWindow)->nextWindow)->previousWindow = theWindow; (*curTransWindow)->nextWindow = theWindow; // fix end of list if ((*theWindow)->nextWindow == nil) { if ((*theWindow)->windowKind&kTSMWindow) gCommRec.tsmLastWindow = theWindow; else (*((*theWindow)->owner))->lastWindow = theWindow; } } break; } curWindow = (WindowPtr)((WindowPeek)curWindow)->nextWindow; } } break; default: break; } } // if a WindowPtr happens to be the global window for an application return the app record X_Ray_AppRecHandle WindowIsGlobalAppWindow (WindowPtr theWindow) { X_Ray_AppRecHandle curApp; curApp = gCommRec.appList; while (curApp) { if (theWindow == (WindowPtr)(*curApp)->appGlobalWindow) return curApp; curApp = (*curApp)->nextApp; } return nil; } // makes sure that a normal window's old location is refreshed properly when the window is moved // and it intersected transparent windows behind it at its old location // this fixes underlying window frames that do not redraw correctly void AssureOldWindowLocationIsRefreshed (WindowPtr theWindow, RgnHandle oldStrucRgn) { RgnHandle cur_intersectRgn; Boolean doRefresh = false; GrafPtr origPort; WindowPtr nextWind; if (!IsWindowTransparent(theWindow)) { GetPort (&origPort); cur_intersectRgn = NewRgn(); nextWind = (WindowPtr)((WindowPeek)theWindow)->nextWindow; while (nextWind && !doRefresh) { if (IsWindowTransparent(nextWind)) { SectRgn (oldStrucRgn, ((WindowPeek)nextWind)->contRgn, cur_intersectRgn); if (!EmptyRgn (cur_intersectRgn)) doRefresh = true; // found an intersection, redraw } nextWind = (WindowPtr)((WindowPeek)nextWind)->nextWindow; } if (doRefresh) PaintBehind (theWindow, oldStrucRgn); DisposeRgn (cur_intersectRgn); } } // makes sure that normal windows get refreshed properly when brought in front of // transparent windows in the same layer void AssureMovingWindowIsRefreshed (WindowPtr theWindow) { RgnHandle cur_visRgn, cur_intersectRgn, accumulated_VisUpdateRgn, accumulated_StrucUpdateRgn; GrafPtr origPort; WindowPtr nextWind; if (!IsWindowTransparent(theWindow)) { GetPort (&origPort); cur_visRgn = NewRgn(); cur_intersectRgn = NewRgn(); accumulated_VisUpdateRgn = NewRgn(); accumulated_StrucUpdateRgn = NewRgn(); SetPort (theWindow); CopyRgn (theWindow->visRgn, cur_visRgn); X_Ray_LocalToGlobalRgn (cur_visRgn); nextWind = (WindowPtr)((WindowPeek)theWindow)->nextWindow; while (nextWind) { if (IsWindowTransparent(nextWind)) { // accumulate the vis rgn intersections SectRgn (cur_visRgn, ((WindowPeek)nextWind)->contRgn, cur_intersectRgn); if (!EmptyRgn (cur_intersectRgn)) UnionRgn (cur_intersectRgn, accumulated_VisUpdateRgn, accumulated_VisUpdateRgn); // accumulate normal struc rgn - transparent contRgn intersections SectRgn (((WindowPeek)theWindow)->strucRgn, ((WindowPeek)nextWind)->contRgn, cur_intersectRgn); if (!EmptyRgn (cur_intersectRgn)) UnionRgn (cur_intersectRgn, accumulated_StrucUpdateRgn, accumulated_StrucUpdateRgn); } nextWind = (WindowPtr)((WindowPeek)nextWind)->nextWindow; } if (!EmptyRgn (accumulated_VisUpdateRgn)) { SetPort (theWindow); X_Ray_GlobalToLocalRgn (accumulated_VisUpdateRgn); InvalRgn (accumulated_VisUpdateRgn); } if (!EmptyRgn (accumulated_StrucUpdateRgn)) PaintBehind (theWindow, accumulated_StrucUpdateRgn); DisposeRgn (cur_visRgn); DisposeRgn (cur_intersectRgn); DisposeRgn (accumulated_VisUpdateRgn); DisposeRgn (accumulated_StrucUpdateRgn); SetPort (origPort); } } // returns the next standard Mac OS window behind theWindow // if theWindow is nil, the front most window of all layers is returned // the returned window may be in any layer // *curApp is a reference to the current layer that owns theWindow // if *curApp is nil upon exit and theWindow is not nil, then theWindow is a TSM window WindowPtr GetNextNormalWindow (WindowPtr theWindow, X_Ray_AppRecHandle *curApp) { if (curApp == nil) return nil; if (theWindow == nil) { *curApp = nil; GetFrontServiceWindow (&theWindow); if (theWindow == nil) { *curApp = gCommRec.appList; while (*curApp) { theWindow = GetFirstLayerWindow ((LayerPtr)(*(*curApp))->appGlobalWindow); if (theWindow == nil) *curApp = (*(*curApp))->nextApp; else break; } } } else { theWindow = (WindowPtr)((WindowPeek)theWindow)->nextWindow; if (theWindow == nil) { if (*curApp == nil) *curApp = gCommRec.appList; else *curApp = (*(*curApp))->nextApp; while (*curApp) { theWindow = GetFirstLayerWindow ((LayerPtr)(*(*curApp))->appGlobalWindow); if (theWindow == nil) *curApp = (*(*curApp))->nextApp; else break; } } } return theWindow; } // returns the transwin in front of theWindow // if theWindow is nil, the back most transwin is returned // the returned transwin may be in any layer X_Ray_WindowHandle GetNextWindowAbove (X_Ray_WindowHandle theWindow) { X_Ray_WindowHandle tempWin; X_Ray_AppRecHandle curApp; // passed in nil so return the back most transparent window if (theWindow == nil) { curApp = gCommRec.appList; while ((*curApp)->nextApp) // walk to end of app list curApp = (*curApp)->nextApp; while (curApp && (theWindow == nil)) { theWindow = (*curApp)->lastWindow; curApp = (*curApp)->previousApp; } if (theWindow == nil) theWindow = gCommRec.tsmLastWindow; } else { tempWin = theWindow; theWindow = (*theWindow)->previousWindow; // move forward through the list if (theWindow == nil) // ran out of transWins, look for them in other apps or in the TSM window list { if (!((*tempWin)->windowKind&kTSMWindow)) // current trans window isn't a TSM window { curApp = (*(*tempWin)->owner)->previousApp; while (curApp && (theWindow == nil)) { theWindow = (*curApp)->lastWindow; curApp = (*curApp)->previousApp; } // even after searching all the app lists, theWindow is still nil // so try looking at the tsmWindowList if (theWindow == nil) theWindow = gCommRec.tsmLastWindow; } } } return theWindow; } // returns the next transwin behind theWindow // if theWindow is nil, the front most transwin is returned // the returned transwin may be in any layer X_Ray_WindowHandle GetNextWindowBehind (X_Ray_WindowHandle theWindow) { X_Ray_WindowHandle tempWin; X_Ray_AppRecHandle curApp; // passed in nil so return the front most transparent window if (theWindow == nil) { theWindow = gCommRec.tsmWindowList; if (theWindow == nil) { curApp = gCommRec.appList; while (curApp && (theWindow == nil)) { theWindow = (*curApp)->windowList; curApp = (*curApp)->nextApp; } } } else { tempWin = theWindow; theWindow = (*theWindow)->nextWindow; // move back through the list if (theWindow == nil) // ran out of transWins, look for them in other apps or in the TSM window list { if (((*tempWin)->windowKind&kTSMWindow)) // current trans window is a TSM window curApp = gCommRec.appList; else curApp = (*(*tempWin)->owner)->nextApp; while (curApp && (theWindow == nil)) { theWindow = (*curApp)->windowList; curApp = (*curApp)->nextApp; } } } return theWindow; } void DumpTransparentWindowList (void) { X_Ray_WindowHandle theWindow = nil; DebugStr ("\p-- START OF LIST --;g"); theWindow = GetNextWindowBehind (theWindow); while (theWindow) { DebugStr (*((WindowPeek)(*theWindow)->theWindow)->titleHandle); theWindow = GetNextWindowBehind (theWindow); } DebugStr ("\p-- END OF LIST --;g"); }